/*
 * @Author: lixu lixu@puchigames.com
 * @Date: 2025-06-16 10:28:18
 * @LastEditors: lixu lixu@puchigames.com
 * @LastEditTime: 2025-06-16 10:40:09
 * @FilePath: /go-helper/utils/time.go
 * @Description: 时间处理工具函数，包含时间格式化、时间计算、时间比较、时区转换等功能
 */
package ixUtils

import (
	"fmt"
	"time"
)

const (
	// 时间格式化模板
	TimeFormat      = "2006-01-02 15:04:05"
	DateFormat      = "2006-01-02"
	TimeFormatShort = "2006-01-02 15:04"
	TimeFormatLong  = "2006-01-02 15:04:05.000"
	TimeFormatRFC   = time.RFC3339
)

// FormatTime 格式化时间为字符串
func FormatTime(t time.Time, format string) string {
	if format == "" {
		format = TimeFormat
	}
	return t.Format(format)
}

// ParseTime 解析时间字符串
func ParseTime(timeStr, format string) (time.Time, error) {
	if format == "" {
		format = TimeFormat
	}
	return time.Parse(format, timeStr)
}

// Now 获取当前时间
func Now() time.Time {
	return time.Now()
}

// Today 获取今天的开始时间
func Today() time.Time {
	now := time.Now()
	return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
}

// Yesterday 获取昨天的开始时间
func Yesterday() time.Time {
	return Today().AddDate(0, 0, -1)
}

// Tomorrow 获取明天的开始时间
func Tomorrow() time.Time {
	return Today().AddDate(0, 0, 1)
}

// StartOfDay 获取指定时间的开始时间
func StartOfDay(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}

// EndOfDay 获取指定时间的结束时间
func EndOfDay(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, t.Location())
}

// StartOfWeek 获取指定时间所在周的开始时间（周一）
func StartOfWeek(t time.Time) time.Time {
	weekday := int(t.Weekday())
	if weekday == 0 {
		weekday = 7
	}
	return StartOfDay(t.AddDate(0, 0, -weekday+1))
}

// EndOfWeek 获取指定时间所在周的结束时间（周日）
func EndOfWeek(t time.Time) time.Time {
	weekday := int(t.Weekday())
	if weekday == 0 {
		weekday = 7
	}
	return EndOfDay(t.AddDate(0, 0, 7-weekday))
}

// StartOfMonth 获取指定时间所在月的开始时间
func StartOfMonth(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
}

// EndOfMonth 获取指定时间所在月的结束时间
func EndOfMonth(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month()+1, 0, 23, 59, 59, 999999999, t.Location())
}

// StartOfYear 获取指定时间所在年的开始时间
func StartOfYear(t time.Time) time.Time {
	return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
}

// EndOfYear 获取指定时间所在年的结束时间
func EndOfYear(t time.Time) time.Time {
	return time.Date(t.Year(), 12, 31, 23, 59, 59, 999999999, t.Location())
}

// IsToday 判断时间是否为今天
func IsToday(t time.Time) bool {
	now := time.Now()
	return t.Year() == now.Year() && t.Month() == now.Month() && t.Day() == now.Day()
}

// IsSameDay 判断两个时间是否为同一天
func IsSameDay(t1, t2 time.Time) bool {
	return t1.Year() == t2.Year() && t1.Month() == t2.Month() && t1.Day() == t2.Day()
}

// IsWeekend 判断时间是否为周末
func IsWeekend(t time.Time) bool {
	weekday := t.Weekday()
	return weekday == time.Saturday || weekday == time.Sunday
}

// IsWorkday 判断时间是否为工作日
func IsWorkday(t time.Time) bool {
	return !IsWeekend(t)
}

// AddDays 增加天数
func AddDays(t time.Time, days int) time.Time {
	return t.AddDate(0, 0, days)
}

// AddMonths 增加月数
func AddMonths(t time.Time, months int) time.Time {
	return t.AddDate(0, months, 0)
}

// AddYears 增加年数
func AddYears(t time.Time, years int) time.Time {
	return t.AddDate(years, 0, 0)
}

// DiffDays 计算两个时间相差的天数
func DiffDays(t1, t2 time.Time) int {
	t1 = StartOfDay(t1)
	t2 = StartOfDay(t2)
	return int(t2.Sub(t1).Hours() / 24)
}

// DiffMonths 计算两个时间相差的月数
func DiffMonths(t1, t2 time.Time) int {
	year1, month1, _ := t1.Date()
	year2, month2, _ := t2.Date()
	return (year2-year1)*12 + int(month2-month1)
}

// DiffYears 计算两个时间相差的年数
func DiffYears(t1, t2 time.Time) int {
	year1, _, _ := t1.Date()
	year2, _, _ := t2.Date()
	return year2 - year1
}

// TimeToUnix 时间转时间戳（秒）
func TimeToUnix(t time.Time) int64 {
	return t.Unix()
}

// TimeToUnixMilli 时间转时间戳（毫秒）
func TimeToUnixMilli(t time.Time) int64 {
	return t.UnixMilli()
}

// UnixToTime 时间戳（秒）转时间
func UnixToTime(timestamp int64) time.Time {
	return time.Unix(timestamp, 0)
}

// UnixMilliToTime 时间戳（毫秒）转时间
func UnixMilliToTime(timestamp int64) time.Time {
	return time.Unix(timestamp/1000, (timestamp%1000)*1000000)
}

// FormatDuration 格式化时间间隔
func FormatDuration(d time.Duration) string {
	if d < time.Second {
		return fmt.Sprintf("%dms", d.Milliseconds())
	}
	if d < time.Minute {
		return fmt.Sprintf("%.1fs", d.Seconds())
	}
	if d < time.Hour {
		return fmt.Sprintf("%.1fm", d.Minutes())
	}
	if d < 24*time.Hour {
		return fmt.Sprintf("%.1fh", d.Hours())
	}
	return fmt.Sprintf("%.1fd", d.Hours()/24)
}

// GetAge 计算年龄
func GetAge(birthday time.Time) int {
	now := time.Now()
	age := now.Year() - birthday.Year()
	if now.Month() < birthday.Month() || (now.Month() == birthday.Month() && now.Day() < birthday.Day()) {
		age--
	}
	return age
}

// IsLeapYear 判断是否为闰年
func IsLeapYear(year int) bool {
	return year%4 == 0 && (year%100 != 0 || year%400 == 0)
}

// GetDaysInMonth 获取指定年月的天数
func GetDaysInMonth(year int, month time.Month) int {
	return time.Date(year, month+1, 0, 0, 0, 0, 0, time.Local).Day()
}

// GetWeekNumber 获取指定时间是一年中的第几周
func GetWeekNumber(t time.Time) int {
	_, week := t.ISOWeek()
	return week
}

// GetQuarter 获取指定时间是一年中的第几季度
func GetQuarter(t time.Time) int {
	return int(t.Month()-1)/3 + 1
}

// CurrentUnix 获取当前时间戳（秒）
func CurrentUnix() int64 {
	return time.Now().Unix()
}

// CurrentUnixMilli 获取当前时间戳（毫秒）
func CurrentUnixMilli() int64 {
	return time.Now().UnixMilli()
}

// CurrentUnixNano 获取当前时间戳（纳秒）
func CurrentUnixNano() int64 {
	return time.Now().UnixNano()
}

// CurrentTime 获取当前时间字符串，格式：2006-01-02 15:04:05
func CurrentTime() string {
	return time.Now().Format(TimeFormat)
}

// CurrentDate 获取当前日期字符串，格式：2006-01-02
func CurrentDate() string {
	return time.Now().Format(DateFormat)
}

// CurrentTimeShort 获取当前时间字符串（短格式），格式：2006-01-02 15:04
func CurrentTimeShort() string {
	return time.Now().Format(TimeFormatShort)
}

// CurrentTimeLong 获取当前时间字符串（长格式），格式：2006-01-02 15:04:05.000
func CurrentTimeLong() string {
	return time.Now().Format(TimeFormatLong)
}

// CurrentTimeRFC 获取当前时间字符串（RFC格式）
func CurrentTimeRFC() string {
	return time.Now().Format(TimeFormatRFC)
}

//  ---------------------时区---------------------------------------

// GetLocation 获取指定时区
func GetLocation(timezone string) (*time.Location, error) {
	return time.LoadLocation(timezone)
}

// GetLocalLocation 获取本地时区
func GetLocalLocation() *time.Location {
	return time.Local
}

// GetUTCLocation 获取UTC时区
func GetUTCLocation() *time.Location {
	return time.UTC
}

// GetChinaLocation 获取中国时区
func GetChinaLocation() *time.Location {
	return time.FixedZone("CST", 8*3600)
}

// ToLocation 将时间转换到指定时区
func ToLocation(t time.Time, timezone string) (time.Time, error) {
	loc, err := GetLocation(timezone)
	if err != nil {
		return t, err
	}
	return t.In(loc), nil
}

// ToUTC 将时间转换为UTC时间
func ToUTC(t time.Time) time.Time {
	return t.UTC()
}

// ToLocal 将时间转换为本地时间
func ToLocal(t time.Time) time.Time {
	return t.Local()
}

// ToChina 将时间转换为中国时区
func ToChina(t time.Time) time.Time {
	return t.In(GetChinaLocation())
}

// GetTimezoneOffset 获取指定时区与UTC的偏移量（秒）
func GetTimezoneOffset(timezone string) (int, error) {
	loc, err := GetLocation(timezone)
	if err != nil {
		return 0, err
	}
	_, offset := time.Now().In(loc).Zone()
	return offset, nil
}

// GetTimezoneName 获取指定时区的名称
func GetTimezoneName(timezone string) (string, error) {
	loc, err := GetLocation(timezone)
	if err != nil {
		return "", err
	}
	return loc.String(), nil
}

// IsDST 判断指定时区是否处于夏令时
func IsDST(timezone string) (bool, error) {
	loc, err := GetLocation(timezone)
	if err != nil {
		return false, err
	}
	_, offset := time.Now().In(loc).Zone()
	_, stdOffset := time.Now().In(loc).UTC().Zone()
	return offset != stdOffset, nil
}

// GetTimezoneAbbr 获取指定时区的缩写
func GetTimezoneAbbr(timezone string) (string, error) {
	loc, err := GetLocation(timezone)
	if err != nil {
		return "", err
	}
	now := time.Now().In(loc)
	return now.Format("MST"), nil
}

// GetTimezoneList 获取所有可用的时区列表
func GetTimezoneList() []string {
	zones := []string{
		"UTC",
		"Local",
		"Asia/Shanghai",
		"Asia/Chongqing",
		"Asia/Urumqi",
		"Asia/Hong_Kong",
		"Asia/Tokyo",
		"Asia/Seoul",
		"Asia/Singapore",
		"Europe/London",
		"Europe/Paris",
		"Europe/Berlin",
		"America/New_York",
		"America/Los_Angeles",
		"America/Chicago",
		"Australia/Sydney",
		"Pacific/Auckland",
	}
	return zones
}

// IsValidTimezone 判断时区是否有效
func IsValidTimezone(timezone string) bool {
	_, err := GetLocation(timezone)
	return err == nil
}

// GetCurrentTimezone 获取当前时区
func GetCurrentTimezone() string {
	return time.Now().Location().String()
}

// GetCurrentTimezoneOffset 获取当前时区与UTC的偏移量（秒）
func GetCurrentTimezoneOffset() int {
	_, offset := time.Now().Zone()
	return offset
}

// GetCurrentTimezoneAbbr 获取当前时区的缩写
func GetCurrentTimezoneAbbr() string {
	return time.Now().Format("MST")
}

// IsCurrentDST 判断当前是否处于夏令时
func IsCurrentDST() bool {
	_, offset := time.Now().Zone()
	_, stdOffset := time.Now().UTC().Zone()
	return offset != stdOffset
}
